package com.example.plan.controller;

import com.example.plan.common.result.Result;
import com.example.plan.exception.ErrorCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName VideoSreeamController
 * @Description TODO
 * @Author renhong~Deng
 * @Date 2025/3/23 12:23
 * @Version 1.0
 */

@Api(tags = "视频流接口")
@RestController
@RequestMapping("/v1/")
public class VideoStreamController {

    private static final Logger logger = LoggerFactory.getLogger(VideoStreamController.class);

    // 定义一个映射来存储视频ID和对应的视频路径
    private static final Map<String, String> VIDEO_PATHS = new HashMap<>();

    static {
        // 初始化视频路径映射
        VIDEO_PATHS.put("video1", "G:\\computer-competition\\video1.mp4");
        VIDEO_PATHS.put("video2", "G:\\computer-competition\\video2.mp4");
        VIDEO_PATHS.put("video3", "G:\\computer-competition\\video3.mp4");
        VIDEO_PATHS.put("video4", "G:\\computer-competition\\video4.mp4");
    }

    /**
     * 流式传输视频
     * @param videoId 视频ID，用于从映射中获取视频路径
     * @param rangeHeader Range头，用于支持断点续传
     * @return ResponseEntity<Resource> 视频资源的响应实体
     */
    @ApiOperation(value = "流式传输视频", notes = "根据视频ID流式传输视频，支持Range头以实现断点续传")
    @ApiResponses({
            @ApiResponse(code = 200, message = "视频流传输成功"),
            @ApiResponse(code = 206, message = "部分内容传输成功"),
            @ApiResponse(code = 40400, message = "视频未找到"),
            @ApiResponse(code = 50000, message = "服务器内部错误")
    })
    @GetMapping("stream_video")
    public ResponseEntity<Resource> streamVideo(
            @ApiParam(value = "视频ID", required = true, example = "video1") @RequestParam String videoId,
            @ApiParam(value = "Range头", required = false, example = "bytes=0-1023") @RequestHeader(value = "Range", required = false) String rangeHeader) {
        try {
            // 根据视频ID获取视频路径
            String videoPathStr = VIDEO_PATHS.get(videoId);
            if (videoPathStr == null) {
                // 如果视频ID不存在，返回404 Not Found
                logger.error("视频id未找到： {}", videoId);
                return ResponseEntity.status(ErrorCode.NOT_FOUND_ERROR.getCode())
                        .body(null);
            }
            logger.info("视频id找到： {}", videoId);

            // 将视频路径字符串转换为Path对象
            Path videoPath = Paths.get(videoPathStr);
            logger.info("视频路径: {}", videoPath);
            // 检查视频路径是否存在
            if (!videoPath.toFile().exists()) {
                // 如果视频路径不存在，返回404 Not Found
                logger.error("视频路径不存在: {}", videoPath);
                return ResponseEntity.status(ErrorCode.NOT_FOUND_ERROR.getCode())
                        .body(null);
            }
            logger.info("视频路径存在: {}", videoPath);

            // 创建UrlResource对象
            Resource videoResource = new UrlResource(videoPath.toUri());

            // 检查视频资源是否存在
            if (!videoResource.exists()) {
                // 如果视频资源不存在，返回404 Not Found
                logger.error("视频资源不存在: {}", videoPath);
                return ResponseEntity.status(ErrorCode.NOT_FOUND_ERROR.getCode())
                        .body(null);
            }
            logger.info("视频资源存在: {}", videoPath);

            // 获取视频内容长度
            long contentLength = videoResource.contentLength();
            logger.info("视频内容长度: {}", contentLength);
            // 创建HttpHeaders对象
            HttpHeaders headers = new HttpHeaders();
            // 设置Content-Type为video/mp4
            headers.setContentType(MediaType.parseMediaType("video/mp4"));
            // 设置Content-Length
            headers.setContentLength(contentLength);

            // 处理Range头（支持断点续传）
            if (rangeHeader != null) {
                long start = 0;
                long end = contentLength - 1;
                // 解析Range头
                String[] ranges = rangeHeader.substring(6).split("-");
                if (ranges.length > 1) {
                    try {
                        start = Long.parseLong(ranges[0]);
                        end = Long.parseLong(ranges[1]);
                    } catch (NumberFormatException e) {
                        logger.error("Invalid range header: {}", rangeHeader, e);
                        return ResponseEntity.status(ErrorCode.PARAMS_ERROR.getCode()).body(null);
                    }
                } else {
                    try {
                        start = Long.parseLong(ranges[0]);
                    } catch (NumberFormatException e) {
                        logger.error("Invalid range header: {}", rangeHeader, e);
                        return ResponseEntity.status(ErrorCode.PARAMS_ERROR.getCode()).body(null);
                    }
                }
                // 确保end不超过文件长度
                if (end > contentLength - 1) {
                    end = contentLength - 1;
                }
                long chunkSize = end - start + 1;
                // 设置Content-Range头
                headers.add(HttpHeaders.CONTENT_RANGE, "bytes " + start + "-" + end + "/" + contentLength);
                // 设置Content-Length为分块大小
                headers.setContentLength(chunkSize);
                // 返回206 Partial Content状态码
                logger.info("Partial Content状态码: {}, range: {}-{}", videoId, start, end);
                return ResponseEntity.status(206).headers(headers).body(videoResource);
            }

            // 如果没有Range头，返回整个视频资源
            logger.info("如果没有Range头，返回整个视频资源，id: {}", videoId);
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(videoResource);
        } catch (Exception e) {
            // 打印异常堆栈信息
            logger.error("Error streaming video: ", e);
            // 返回500 Internal Server Error状态码
            return ResponseEntity.status(ErrorCode.SYSTEM_ERROR.getCode())
                    .body(null);
        }
    }
}